/*
0 * monitor.cpp
 *
 *  Created on: 15/11/2014
 *      Author: dario
 */

#include <time.h>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <semaphore.h>
#include "monitor.h"

using namespace std;

int main() {
	pidProcesoPadre = getppid();
	cout << "[Monitor] Pid padre: " << pidProcesoPadre << endl;
	char nombre_key[] = "/bin/cp";
	int number_key_mem = 222;
	sem_name_M = (char*) malloc(sizeof(char) * 12);
	strcpy(sem_name_M, "/semMemoria");

	SEM_M = sem_open(sem_name_M, 0); /* Asocio el semáforo, asumo que lo creó el Servidor */
	if(SEM_M == SEM_FAILED) {
		cerr << "[Monitor] Error al abrir el Semáforo" << endl;
		exit(EXIT_FAILURE);
	}

	/* Obtenemos una clave para la memoria compartida */
	key_t memory_key;
	memory_key = ftok(nombre_key, number_key_mem);
	if (memory_key == -1) {
		cerr << "[Monitor] Linea 41. No consigo clave para memoria compartida" << endl;
		exit(EXIT_FAILURE);
	}

	/* Obtenemos el id de la memoria. Al no poner el flag IPC_CREAT,
	 * estamos suponiendo que dicha memoria ya está creada. */
	memory_id = shmget(memory_key, sizeof(t_torneo), 0666 );
	if (memory_id == -1) {
		cerr << "[Monitor] Linea 49. No consigo Id para memoria compartida" << endl;
		exit(EXIT_FAILURE);
	}
	printf("\nId de memoria: %d\n", memory_id);
	/* Obtenemos un puntero a la memoria compartida */
	torneo = (t_torneo *)shmat(memory_id, (char *)0, 0);
	if (torneo == NULL) {
		cerr << "[Monitor] Linea 56. No consigo memoria compartida" << endl;
		exit(EXIT_FAILURE);
	}
	printf("\nDireccion de memoria: %p\n", torneo);

	ignoreSignals();
	signal(SIGTERM, exitProcessMonitor);

	while(1) {
		sleep(4);
		if(pidProcesoPadre != getppid()) { /* Si cambia el pid es porque murió el proceso padre */
			matarProcesosYEnviarMensajesFin();
			cerrarRecursosYTerminarEjecucion();
		}
		cout << "[Monitor] Linea 69. Proceso Servidor Corriendo" << endl;
	}
	return 0;
}

void matarProcesosYEnviarMensajesFin() {
	int i;
	if (sem_wait(SEM_M) == -1) { /* tomo el semaforo. */
		cerr << "[Monitor] Linea 76. Failed waiting semaphore\n" << endl;
		exit(EXIT_FAILURE);
	}
	for (i = 0; i < torneo->cantJugadores; i++) {
		//send(torneo->jugador[i].socket , message , strlen(message) , 0);
		close(torneo->jugador[i].socket); /* Cierro todas los sockets de los clientes */
	}

	for (i = 0; i < torneo->cantPartidas; i++) {
		kill(torneo->partidas[i].pid, SIGKILL); /* Cierro todas las partidas */
	}

	if (sem_post(SEM_M) == -1) { /* libero el semaforo. */
		cerr << "[Monitor] Linea 87. Failed waiting semaphore\n" << endl;
		exit(EXIT_FAILURE);
	}
}

void exitProcessMonitor(int sign) {
	/* Desasociamos nuestro puntero de la memoria compartida. Suponemos
	 * que p1 (el proceso que la ha creado), la liberará. */
	cout << "[Monitor] Linea 130. Desasociando memoria" << endl;
	if (memory_id != -1) {
		shmdt((char *) torneo);
	}
	cout << endl << "[Monitor] Linea 134. FIN PROCESO MONITOR" << endl;
	exit(EXIT_SUCCESS);
}

void cerrarRecursosYTerminarEjecucion() {
	cout << "[Monitor] Linea 138. Cerrando recursos" << endl;
	printf("\nDireccion de memoria: %p", torneo);
	getsid(getpid());
	/* Terminada de usar la memoria compartida, la liberamos. */
	shmdt((void*)torneo); /* Desasocia la memoria compartida de la zona de nuestro programa. Solo un proceso. */
	shmctl(memory_id, IPC_RMID, (struct shmid_ds *)NULL); /* Destruye la zona de MComp. Solo un proceso. */

	sem_close(SEM_M);/* desasocio el semaforo. */
	sem_unlink(sem_name_M);/* destruyo el semaforo */

	sem_unlink("/semPartidas");
	cout << "[Monitor] Linea 118. FIN PROCESO MONITOR" << endl;
	exit(EXIT_FAILURE);
}

void ignoreSignals() {
	signal(SIGINT, SIG_IGN);
	signal(SIGABRT, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGSEGV, SIG_IGN);
	signal(SIGUSR1, SIG_IGN);
	signal(SIGUSR2, SIG_IGN);
}
